<template>
  <div v-loading="loading" style="min-width: 900px; height: 100%;">
    <div v-if="nodeData && nodeData.nodeList && nodeData.nodeList.length > 0" class="fixedLeft">
      <div v-for="(item,index) in nodeData.nodeList" :key="index" class="flex" :class="index === 0 ? 'mt' : ''">
        <div :style="'background:'+item.color" />
        <div><span style="font-size: 10px">{{ item.label }} ({{ item.num }})个</span></div>
      </div>
    </div>
    <div id="container" style="position:absolute;width:97%; min-height:700px;margin:0 auto;background-color: white" />
  </div>
</template>

<script>
import G6 from '@antv/g6'
export default {
  components: {
  },
  props: {
    nodeListData: {
      type: Array,
      default: () => []
    },
    // 是否展示下拉开关.
    isShowLevel: {
      type: Boolean,
      default: false
    },
    // 布局方式
    ofType: {
      type: String,
      default: () => {
        return 'top'
      }
    }
  },
  data() {
    return {
      investorType: undefined,
      investorId: undefined,
      // 表单参数
      form: {},
      // 遮罩层
      loading: false,
      // 表单校验
      rules: {},
      nodeData: {},
      dataList: {},
      graph: undefined,
      dataCc: {
        nodes: [],
        edges: []
      }
    }
  },
  watch: {
    nodeListData: {
      handler(val) {
        this.nodeData = JSON.parse(JSON.stringify(val))
        this.$nextTick(() => {
          this.getData()
        })
      },
      deep: true,
      immediate: true
    }
  },
  created() {
  },
  mounted() {
  },
  methods: {
    // 初始化数据
    getData() {
      this.loading = true
      if (this.graph !== undefined) {
        this.graph.destroy()
      }
      this.dataList.nodeList = this.nodeData.nodeList
      this.dataList.nodes = this.nodeData.nodes
      this.dataList.edges = this.nodeData.edges
      this.dataCc = {
        nodes: [],
        edges: []
      }
      this.dataList.nodes.forEach((item, k) => {
        if (item.id === '1') {
          item.anchorPoints = [[0.5, 1]]
        } else {
          item.anchorPoints = [[0.5, 0]]
          // item.anchorPoints = [[0.5, 1], [0.5, 0.5], [0, 0.5]]
        }
        item.name = this.getName(item.name, k)
      })
      this.show()
      this.loading = false
    },
    show() {
      var that = this
      G6.registerNode('dom-node', {
        draw: (cfg, group) => {
          if (!cfg.isHidden || cfg.isHidden === false) {
            // const stroke = cfg.style ? cfg.style.stroke || '#5B8FF9' : '#5B8FF9'
            const shape = group.addShape('dom', {
              attrs: {
                width: cfg.width,
                height: cfg.height,
                html: `<div
                         id="nodeClick"
                         style="width: ${cfg.width}px; height:${cfg.height}px; background:${cfg.bgColor ? cfg.bgColor : '#00287E'}; color:#fff; border:2px solid #aaa; padding:0; text-align:Center; box-sizing:border-box; display:flex; align-items: center; justify-content: center;"
                       ><span>${cfg.name}</span></div>`
              },
              draggable: true
            })
            if (that.selectChild(cfg.id) && this.isShowLevel) {
              group.addShape('marker', {
                attrs: {
                  x: cfg.width / 2,
                  y: cfg.height - 1,
                  r: 10,
                  cursor: 'pointer',
                  symbol: G6.Marker.collapse,
                  stroke: '#666',
                  lineWidth: 2,
                  fill: '#fff'
                },
                name: 'collapse-icon'
              })
            }
            return shape
          }
        },
        setState(name, value, item) {
          if (name === 'collapsed') {
            const marker = item.get('group').find((ele) => ele.get('name') === 'collapse-icon')
            const icon = value ? G6.Marker.expand : G6.Marker.collapse
            marker.attr('symbol', icon)
          }
        }
      })
      G6.registerEdge('flow-line', {
        draw(cfg, group) {
          const startPoint = cfg.startPoint
          const endPoint = cfg.endPoint
          const { style } = cfg
          var shape
          if (!cfg.isHidden) {
            if (cfg.border && cfg.border === 'none') {
              shape = group.addShape('path', {
                attrs: {
                  stroke: '#409EFF',
                  endArrow: style.endArrow,
                  path: [
                    ['M', startPoint.x, startPoint.y],
                    ['L', startPoint.x, (startPoint.y + endPoint.y) / 2 + 35],
                    ['L', endPoint.x, (startPoint.y + endPoint.y) / 2 + 35]
                  ]
                }
              })
            } else {
              shape = group.addShape('path', {
                attrs: {
                  stroke: ((style.lColor === undefined || style.lColor === null) ? '#409EFF' : style.lColor),
                  endArrow: style.endArrow,
                  path: [
                    ['M', startPoint.x, startPoint.y],
                    ['L', startPoint.x, (startPoint.y + endPoint.y) / 2 + 35],
                    ['L', endPoint.x, (startPoint.y + endPoint.y) / 2 + 35],
                    ['L', endPoint.x, endPoint.y]
                  ]
                }
              })
            }
            group.addShape('text', {
              attrs: {
                text: cfg.label,
                fontSize: 16,
                fill: '#595959',
                textAlign: 'center',
                textBaseline: 'middle',
                x: that.ofType === 'top' ? cfg.endPoint.x + 35 : startPoint.x - 35,
                y: that.ofType === 'top' ? cfg.endPoint.y - 70 : startPoint.y + 150
              }
            })
            return shape
          }
        }
      })
      const container = document.getElementById('container')
      const width = container ? container.scrollWidth : 1300
      const height = this.$el ? (this.$el.scrollHeight === undefined ? 650 : this.$el.scrollHeight) : 650
      // const minimap = new G6.Minimap({
      //   size: [130, 82],
      //   attr: {
      //     style: {
      //       position: 'absolute',
      //       right: '10px',
      //       top: '10px'
      //     }
      //   }
      // })
      this.graph = new G6.Graph({
        container: 'container',
        width,
        height,
        renderer: 'svg',
        layout: {
          type: 'dagre',
          // nodesepFunc: (d) => {
          //   if (d.id !== '1') {
          //     return 50
          //   } else {
          //     return 100
          //   }
          // },
          // ranksep: 100,
          rankdir: 'TB',
          ranksepFunc: (d) => {
            console.log(d)
            return 100
          },
          ranksep: 70,
          controlPoints: true
        },
        defaultNode: {
          type: 'dom-node'
        },
        // 边的样式配置
        defaultEdge: {
          type: 'flow-line',
          //  边样式配置
          style: {
            stroke: '#ffa600'
          },
          labelCfg: {
            // position: 'center'
          }
        },
        nodeStateStyles: {
          selected: {
            stroke: '#d9d9d9',
            fill: '#ffa600'
          }
        },
        modes: {
          default: ['drag-canvas', 'zoom-canvas'],
          enableOptimize: true,
          labelCfg: {
            style: {
              fill: '#fff',
              fontSize: 14,
              textAlign: 'center'
            }
          }
        },
        fitView: true,
        preventOverlap: true
        // plugins: [minimap]
      })
      this.graph.on('node:click', e => {
        if (e.target.get('name') === 'collapse-icon') {
          e.item.getModel().collapsed = !e.item.getModel().collapsed
          this.graph.setItemState(e.item, 'collapsed', e.item.getModel().collapsed)
          this.updateDataList(e.item._cfg.id, e.item.getModel().collapsed)
          //  graph.layout()
        }
      })

      this.graph.data(this.dataList)
      this.graph.render()

      if (typeof window !== 'undefined') {
        window.onresize = () => {
          if (!this.graph || this.graph.get('destroyed')) return
          if (!container || !container.scrollWidth || !container.scrollHeight) return
          this.graph.changeSize(container.scrollWidth, container.scrollHeight)
        }
      }
      if (this.dataList.nodes.length > 5) {
        this.graph.zoom(0.8, { x: container.scrollWidth / 2, y: container.scrollHeight / 2 })
      } else if (this.dataList.nodes.length > 3) {
        this.graph.zoom(0.7, { x: container.scrollWidth / 2, y: container.scrollHeight / 2 })
      } else if (this.dataList.nodes.length > 2) {
        this.graph.zoom(0.6, { x: container.scrollWidth / 2, y: container.scrollHeight / 2 })
      } else if (this.dataList.nodes.length > 0) {
        this.graph.zoom(0.4, { x: container.scrollWidth / 2, y: container.scrollHeight / 2 })
      }
    },
    getName(name, k) {
      if (k === 0) {
        return name
      } else {
        var str = ''
        for (var i = 0; i < name.length; i++) {
          if (i % 6 === 0) {
            str += '\n'
          }
          str += name[i]
        }
        return str
      }
    },
    // 隐藏恢复节点
    updateDataList(id, type) {
      // 存储需要隐藏的内容
      if (type) {
        this.selectChidrenDelete(id, type)
      } else {
        this.selectChildrenAdd(id, type)
      }
    },
    // 递归查询子级-删除
    selectChidrenDelete(id, type) {
      var nodesList = []
      var edgesList = []
      var ids = []
      this.dataList.edges.forEach((item) => {
        // 把子集的数据临时存放
        if (id === item.source) {
          this.dataCc.edges.push(item)
          ids.push(item.target)
          // 隐藏
          this.graph.find('edge', (edge) => {
            if (edge.get('model').source === item.source) {
              edge._cfg.model.isHidden = true
              this.graph.refreshItem(edge)
            }
          })
        } else {
          edgesList.push(item)
        }
      })
      this.dataList.edges = edgesList

      this.dataList.nodes.forEach((item) => {
        // 隐藏后的节点存储
        if (ids.indexOf(item.id) !== -1) {
          this.dataCc.nodes.push(item)
          // 隐藏
          const el = this.graph.findById(item.id)
          el._cfg.model.isHidden = true
          this.graph.refreshItem(el)
        } else {
          nodesList.push(item)
        }
      })
      this.dataList.nodes = nodesList
      // 如果子集也有下级
      this.dataCc.edges.forEach((item) => {
        if (item.source === id) {
          this.selectChidrenDelete(item.target, type)
        }
      })
    },
    // 递归查询子级-新增
    selectChildrenAdd(id, type) {
      var nodesList = []
      var edgesList = []
      var ids = []
      this.dataCc.edges.forEach((item) => {
        if (item.source === id) {
          // 新增
          this.graph.find('edge', (edge) => {
            if (edge.get('model').source === item.source) {
              edge._cfg.model.isHidden = false
              setTimeout(() => {
                this.graph.refreshItem(edge)
              }, 10)
            }
          })
          this.dataList.edges.push(item)
          ids.push(item.target)
        } else {
          edgesList.push(item)
        }
      })

      this.dataCc.edges = edgesList
      this.dataCc.nodes.forEach((item) => {
        if (ids.indexOf(item.id) !== -1) {
          item.collapsed = false
          // 隐藏
          const el = this.graph.findById(item.id)
          el._cfg.model.isHidden = false
          this.graph.refreshItem(el)
          this.dataList.nodes.push(item)
        } else {
          nodesList.push(item)
        }
      })
      this.dataCc.nodes = nodesList
      // 如果子集也有下级
      this.dataCc.edges.forEach((item) => {
        if (ids.indexOf(item.source) !== -1) {
          this.selectChildrenAdd(item.source, type)
        }
      })
    },
    // 查询是否有子级
    selectChild(id) {
      var num = 0
      var edgeList = this.dataList.edges.concat(this.dataCc.edges)
      edgeList.forEach((item) => {
        if (item.source === id) {
          num++
        }
      })
      if (num === 0) {
        return false
      } else {
        return true
      }
    }
  }

}
</script>

<style lang="scss" scoped>
.fixedLeft {
  position: fixed;
  bottom: 30px;
  box-shadow: #ccc 0 0 20px 2px;
  left: 220px;
  padding: 20px;
  box-sizing: border-box;
  z-index: 999;
  background: #fff;
}

.flex {
  display: flex;
  align-items: center;
  margin-top: 5px;
}

.flex :nth-child(1) {
  width: 50px;
  height: 10px;
  margin-right: 3px;
}

.mt {
  margin-top: 0;
}

.xie {
  border: 1px solid #333;
  width: 200px;
  height: 20px;
  background: linear-gradient(to bottom right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) calc(50% - 1px), rgba(0, 0, 0, 1) 50%, rgba(0, 0, 0, 0) calc(50% + 1px), rgba(0, 0, 0, 0) 100%);
}

.jk2 {
  width: 200px;
  height: 20px;
  background: linear-gradient(to top right, rgba(255, 0, 0, 0) 0%, rgba(255, 0, 0, 0) calc(50% - 1px), rgba(255, 0, 0, 1) 50%, rgba(255, 0, 0, 0) calc(50% + 1px), rgba(255, 0, 0, 0) 100%), linear-gradient(to bottom right, rgba(255, 0, 0, 0) 0%, rgba(255, 0, 0, 0) calc(50% - 1px), rgba(255, 0, 0, 1) 50%, rgba(255, 0, 0, 0) calc(50% + 1px), rgba(255, 0, 0, 0) 100%);
  border: 1px solid red;
}
</style>
